home *** CD-ROM | disk | FTP | other *** search
/ Fritz: All Fritz / All Fritz.zip / All Fritz / FILES / PROGNG_C / DBTOOLC.LZH / SOURCE.ARC / DBARRAY.C next >
C/C++ Source or Header  |  1986-10-08  |  24KB  |  1,005 lines

  1.  
  2. /* 
  3. *
  4. *    NAME:
  5. *       dbarray.c - array function for use from dbase
  6. *
  7. *    SYNOPSIS:
  8. *       cr_array(id, n, type)   -- create an array
  9. *       rn_array(id, newid) -- rename an array
  10. *       fc_array(id)        -- find an array
  11. *       arsize(id)          -- find size of an array
  12. *       fr_array(id)        -- free an array
  13. *       put_arv(id, index, value)-- put a value in an array
  14. *       get_arv(id, index)   -- get a value from an array
  15. *       st_arrays()     -- lists info on all arrays
  16. *       dump_array()    -- dumps contents of an array
  17. *       fdump_array()    -- dumps contents of an array to a disk file
  18. *       arcount()   -- count # elements used so far
  19. *       arsetcnt()  -- reset count of an array
  20. *       aroff()     - parses offset dimension expression
  21. *       save_arr()      - save the array to a disk file
  22. *       rest_arr()  - restore an array from a disk file
  23. *
  24. *    DESCRIPTION:
  25. *       Provide basic array management function for dBASE
  26. *
  27. *    AUTHOR: J. T. Cooper    
  28. *
  29. */
  30.  
  31. #include <stdio.h>
  32. #include <ctype.h>
  33. #include "dctmain.h"
  34.  
  35. #define MAXARRAYS   10   /* max # of arrays in use at one time */
  36. #define MAXDIM        10     /* max # dimensions */
  37. #define BIGARRAY    32000   /* largest # of elements in array */
  38. #define MAXCLEN  255     /* maximum length of character variable */
  39. #define MAXNLEN  8   /* length of numeric variable (same as double)*/
  40.  
  41. struct
  42. {
  43.     char    ar_id[11];  /* array id (name) */
  44.     char    ar_type;    /* memory variable type */
  45.     int     ar_size;    /* max # elements in this array */
  46.     int     ar_count;   /* count of # elements used so far */
  47.     int     ar_ndim;    /* # of dimensions created with */
  48.     int     ar_dims[MAXDIM];
  49.     union
  50.     {
  51.         char    **vchar;  /* beg of character pointer array */
  52.         int *vint;  /* beg of array of integers */
  53.         double  *vdub;   /* beg of array of doubles */
  54.     } ar_val;
  55. } db_ArrayList[MAXARRAYS];
  56.     
  57.  
  58.  
  59. /* 
  60. *
  61. *    NAME:
  62. *       cr_array - create array for dbase
  63. *
  64. *    SYNOPSIS:
  65. *       cr_array(id, s, type)
  66. *       char    *id;    -- ASCIIZ name of array
  67. *       int  s;  -- Dimension expression
  68. *       CHAR    type;   -- 'N' or  'C' variable type
  69. *
  70. *    DESCRIPTION:
  71. *       Creates an array big enough to hold n elements of the
  72. *       given type.
  73. *   
  74. *    RETURNS:
  75. *       Returns the actual number of items the array has room for,
  76. *       which will be n if enough memory is available, or -1
  77. *       if an error occurs.
  78. *   
  79. */
  80.  
  81. cr_array(id, s, type)
  82. char    *id;
  83. char    *s;
  84. char    type;
  85. {
  86. int i,j;
  87. int     n;
  88.  
  89. /* make sure array name isn't already in use */
  90.     for (i = 0; i < MAXARRAYS; i++)
  91.      if (strccmp(db_ArrayList[i].ar_id, id) == 0)
  92.      {
  93.         dctmsg(MSG_IN_USE);
  94.         return -1;
  95.      }
  96.  
  97. /* now find an available slot in the db_ArrayList, if any */
  98.     for (i = 0; i < MAXARRAYS; i++)
  99.     {
  100.      if (*db_ArrayList[i].ar_id == '\0')
  101.         break;
  102.     }
  103.     if (i == MAXARRAYS)
  104.     {
  105.      dctmsg(MSG_NO_MORE);
  106.      return -1;
  107.     }
  108.  
  109. /* convert dimensional expression to actual size of array */
  110.     for (j = 0, n = 1; *s && j < MAXDIM; s++)
  111.     {
  112.         db_ArrayList[i].ar_dims[j] = atoi(s);
  113.         n *= db_ArrayList[i].ar_dims[j++];
  114.         while (isdigit(*s))
  115.             s++;        /* skip past digits we've already used */
  116.         if (toupper(*s) != 'X')
  117.             break;
  118.     }
  119.     db_ArrayList[i].ar_ndim = j;
  120.  
  121. /* make sure he doesn't try to take over the world */
  122.     if (n > BIGARRAY || n < 0)
  123.     {
  124.         dctmsg(MSG_TOO_MANY);
  125.             return -1;
  126.     }
  127.  
  128.  
  129.     db_ArrayList[i].ar_type = toupper(type);
  130.     switch (db_ArrayList[i].ar_type)
  131.     {
  132.     case 'C':
  133.         if (n > 16000)
  134.         {
  135.             dctmsg(MSG_TOO_MANY);
  136.                 return -1;
  137.         }
  138.         db_ArrayList[i].ar_val.vchar = (char **)dctalloc(n, sizeof(char *));
  139.         if (db_ArrayList[i].ar_val.vchar == NULL)
  140.         {
  141.             dctmsg(MSG_NO_SPACE);
  142.             return(-1);
  143.         }
  144.         break;
  145.     case 'N':
  146. #ifdef LARGE
  147.         if (n > 8000)
  148. #else
  149.         if (n > 4000)
  150. #endif
  151.         {
  152.             dctmsg(MSG_TOO_MANY);
  153.                 return -1;
  154.         }
  155.  
  156.         db_ArrayList[i].ar_val.vdub = (double *)dctalloc(n, sizeof(double));
  157.         if (db_ArrayList[i].ar_val.vdub == NULL)
  158.         {
  159.             dctmsg(MSG_NO_SPACE);
  160.             return(-1);
  161.         }
  162.         break;
  163.     default:
  164.         dctmsg(MSG_INV_TYPE);
  165.         return -1;
  166.         break;
  167.     }
  168.     strcpy(db_ArrayList[i].ar_id, id); /* now make it official */
  169.     db_ArrayList[i].ar_size = n;    /* remember how many we have room for */
  170.     db_ArrayList[i].ar_count = 0;   /* no elements yet */
  171.     return n;
  172. }
  173.  
  174. /* 
  175. *
  176. *    NAME:
  177. *       rn_array - rename an array
  178. *
  179. *    SYNOPSIS:
  180. *       rn_array(id, newid)
  181. *       char    *id;    -- ASCIIZ name of array
  182. *       char    *newid; -- new ASCIIZ name of array
  183. *
  184. *    DESCRIPTION:
  185. *       Changes the name of the array <id> to <newid>
  186. *   
  187. *    RETURNS:
  188. *       Sets status variable to 0 if successful, -1 if not. 
  189. */
  190.  
  191. rn_array(id, newid)
  192. char    *id, *newid;
  193. {
  194. int i;
  195.  
  196. /* first see if the array exists */
  197.  
  198.     for (i = 0; i < MAXARRAYS; i++)
  199.     {
  200.      if (strccmp(db_ArrayList[i].ar_id, id) == 0)
  201.        break;
  202.     }
  203.     if (i == MAXARRAYS)
  204.     {
  205.      dctmsg(MSG_NO_ARRAY);
  206.      return -1;
  207.     }
  208.  
  209.     strcpy(db_ArrayList[i].ar_id, newid);
  210.     return(0);
  211. }
  212.  
  213.  
  214. /* 
  215. *
  216. *    NAME:
  217. *       fc_array - find the c array by a given name.
  218. *
  219. *    SYNOPSIS:
  220. *       char *fc_array(id)
  221. *       char    *id;    -- name of array to be found
  222. *
  223. *    DESCRIPTION:
  224. *       Finds the array, if it exists, previously created and
  225. *       given the name matching id.
  226. *   
  227. *    RETURNS:
  228. *       Returns a pointer to the first element in the array if
  229. *       found, otherwise a NULL pointer is returned.
  230. *   
  231. *    NOTES:
  232. *       Returned value must be coerced to the proper type if the
  233. *       array is anything but a character array.
  234. *
  235. */
  236.  
  237. char *fc_array(id)
  238. char    *id;
  239. {
  240. int i;
  241.  
  242.     for (i = 0; i < MAXARRAYS; i++)
  243.     {
  244.      if (strccmp(db_ArrayList[i].ar_id, id) == 0)
  245.         break;
  246.     }
  247.     if (i == MAXARRAYS)
  248.     {
  249.      dctmsg(MSG_NO_ARRAY);
  250.      return ((char *) 0);
  251.     }
  252.  
  253.     switch (db_ArrayList[i].ar_type)
  254.     {
  255.      case 'C':
  256.         return((char *)db_ArrayList[i].ar_val.vchar);
  257.         break;
  258.      case 'N':
  259.         return( (char *)db_ArrayList[i].ar_val.vdub);
  260.         break;
  261.     }
  262.     return((char *)0);
  263. }
  264.  
  265.  
  266. /* 
  267. *
  268. *    NAME:
  269. *       arsize - find the size of an array
  270. *
  271. *    SYNOPSIS:
  272. *       int arsize(id)
  273. *       char *id;   -- name of array
  274. *
  275. *    DESCRIPTION:
  276. *       Determines the size of the array whose name is id.
  277. *   
  278. *    RETURNS:
  279. *       Returns the maximum number of elements for which the
  280. *       array was created to hold, or 0 if the array cannot
  281. *       be found.
  282. *
  283. */
  284.  
  285. arsize(id)
  286. char    *id;
  287. {
  288. int i;
  289.  
  290.     for (i = 0; i < MAXARRAYS; i++)
  291.     {
  292.      if (strccmp(db_ArrayList[i].ar_id, id) == 0)
  293.         break;
  294.     }
  295.     if (i == MAXARRAYS)
  296.         return (0);
  297.  
  298.     return(db_ArrayList[i].ar_size);
  299. }
  300.  
  301.  
  302. /* 
  303. *
  304. *    NAME:
  305. *       arsetcnt - reset the count of elements in an array
  306. *
  307. *    SYNOPSIS:
  308. *       int arsetcnt(id, newcnt)
  309. *       char *id;   -- name of array
  310. *           int newcnt; -- new size of array
  311. *
  312. *    DESCRIPTION:
  313. *       Reset the internal count of the number of elements in 
  314. *           an array. Added primarily for those
  315. *           routines (such as sros) that manipulate members of an
  316. *           array outsize of the normal put_arv function.
  317. *   
  318. *    RETURNS:
  319. *       Returns newcnt if successful, 0 if newcnt is greater 
  320. *       than the maximum elements the array was created to hold.
  321. *   
  322. */
  323.  
  324. arsetcnt(id,newcnt)
  325. char    *id;
  326. int     newcnt;
  327. {
  328. int i;
  329.  
  330.     for (i = 0; i < MAXARRAYS; i++)
  331.     {
  332.      if (strccmp(db_ArrayList[i].ar_id, id) == 0)
  333.         break;
  334.     }
  335.     if (i == MAXARRAYS)
  336.         return (0);
  337.  
  338.     if(newcnt > db_ArrayList[i].ar_size)    /* count > created size? */
  339.     {
  340.         dctmsg(MSG_OUT_OF_BOUNDS);
  341.         return(0);
  342.     }
  343.  
  344.     return(db_ArrayList[i].ar_count = newcnt);
  345.     
  346. }
  347.  
  348.  
  349. /* 
  350. *
  351. *    NAME:
  352. *       arcount - count the # elements used so far (sorta)
  353. *
  354. *    SYNOPSIS:
  355. *       int arcount(id)
  356. *       char *id;   -- name of array
  357. *
  358. *    DESCRIPTION:
  359. *       'Counts' the number of items which have been placed in an 
  360. *       array. If the array has unused slots in between actual 
  361. *       values, those slots will be counted as well. The actual
  362. *       mechanism used is to keep track of the largest index
  363. *       accessed by the put_arv function. Thus, this function can
  364. *       be used to determine the next available slot in the array.
  365. *   
  366. *    RETURNS:
  367. *       Returns the largest index used so far, plus 1. If the array
  368. *           does not exist, -1 is returned.
  369. */
  370.  
  371. arcount(id)
  372. char    *id;
  373. {
  374. int i;
  375.  
  376.     for (i = 0; i < MAXARRAYS; i++)
  377.     {
  378.      if (strccmp(db_ArrayList[i].ar_id, id) == 0)
  379.         break;
  380.     }
  381.     if (i == MAXARRAYS)
  382.         return (-1);
  383.  
  384.     return(db_ArrayList[i].ar_count);
  385. }
  386.  
  387.  
  388. /* 
  389. *
  390. *    NAME:
  391. *       fr_array - free array
  392. *
  393. *    SYNOPSIS:
  394. *       void fr_array(id)
  395. *       char *id;   -- name of array
  396. *
  397. *    DESCRIPTION:
  398. *       Frees all storage taken up by the array and its elements.
  399. *   
  400. *    RETURNS:
  401. *       Returns nothing.
  402. *
  403. */
  404.  
  405. void fr_array(id)
  406. char    *id;
  407. {
  408. int i, j;
  409.  
  410. /* first find the array, if it exists */
  411.  
  412.     for (i = 0; i < MAXARRAYS; i++)
  413.     {
  414.      if (strccmp(db_ArrayList[i].ar_id, id) == 0)
  415.         break;
  416.     }
  417.     if (i == MAXARRAYS)
  418.     {
  419. /* if the name of the array is 'ALL', he wants to free all the arrays */
  420.      if (strccmp(id, "ALL") == 0)
  421.      {
  422.         for (j = 0; j < MAXARRAYS; j++)
  423.         {
  424.             if (*db_ArrayList[j].ar_id)
  425.              fr_array(db_ArrayList[j].ar_id);
  426.         }
  427.      }
  428.      else
  429.         dctmsg(MSG_NO_ARRAY);
  430.      return;
  431.     }
  432.  
  433.  
  434.     switch (db_ArrayList[i].ar_type)
  435.     {
  436.      case 'C':
  437.      /* first free up all string space */
  438.         for(j = 0; j < db_ArrayList[i].ar_count; j++)
  439.             if (db_ArrayList[i].ar_val.vchar[j] != 0)
  440.                 free(db_ArrayList[i].ar_val.vchar[j]);
  441.      /* now free up the array itself */
  442.         free(db_ArrayList[i].ar_val.vchar);
  443.         break;
  444.      case 'N':
  445.         free( (char *) db_ArrayList[i].ar_val.vdub);
  446.         break;
  447.      default:
  448.         dctmsg(MSG_INV_TYPE);
  449.         break;
  450.     }
  451.     *db_ArrayList[i].ar_id = '\0';  /* zap the array name */
  452.     db_ArrayList[i].ar_size = 0;
  453.     db_ArrayList[i].ar_count = 0;
  454. #ifdef LC3
  455.     calloc(0,512);    /* kludge for Lattice 3.0 sizmem() bug */
  456. #endif
  457. }
  458.  
  459.  
  460. /* 
  461. *    NAME:
  462. *       put_arv - put a value into an array
  463. *
  464. *    SYNOPSIS:
  465. *       int put_arv(id, s, value)
  466. *       char *id;   -- array name
  467. *       char *s;    -- offset in array (dimensional expression)
  468. *       char *value;    -- ASCIIZ representation of value
  469. *
  470. *    DESCRIPTION:
  471. *       Converts value to the appropriate type, and stores it
  472. *       in the array whose name is id, at offset s.
  473. *   
  474. *    RETURNS:
  475. *       Returns index if successful, or -1 if an error occurs.
  476. *
  477. */
  478.  
  479. int put_arv(id, s, value)   
  480. char    *id;
  481. char    *s;
  482. char    *value;
  483. {
  484. int i;
  485. int  index;
  486.  
  487. /* first see if the array exists */
  488.  
  489.     for (i = 0; i < MAXARRAYS; i++)
  490.     {
  491.      if (strccmp(db_ArrayList[i].ar_id, id) == 0)
  492.        break;
  493.     }
  494.     if (i == MAXARRAYS)
  495.     {
  496.      dctmsg(MSG_NO_ARRAY);
  497.      return -1;
  498.     }
  499.  
  500.     index = aroff(s, db_ArrayList[i].ar_dims);
  501.  
  502. /* make sure we don't go off the deep end */
  503.     if (index >= db_ArrayList[i].ar_size)
  504.     {
  505.      dctmsg(MSG_OUT_OF_BOUNDS);
  506.      return(-1);
  507.     }
  508. /* now put the value in the array */
  509.     switch (db_ArrayList[i].ar_type)
  510.     {
  511.     case 'C':
  512. /* first free up any previous storage & reallocate for new string */
  513.         if (db_ArrayList[i].ar_val.vchar[index])
  514.             free(db_ArrayList[i].ar_val.vchar[index]);
  515.         db_ArrayList[i].ar_val.vchar[index] = dctalloc(1,strlen(value)+1);
  516.         if (db_ArrayList[i].ar_val.vchar[index] == NULL)
  517.         {
  518.             dctmsg(MSG_NO_SPACE);
  519.             return(-1);
  520.         }
  521.        strcpy(db_ArrayList[i].ar_val.vchar[index], value);
  522.        break;
  523.     case 'N':
  524.        db_ArrayList[i].ar_val.vdub[index] = atof(value);
  525.        break;
  526.     default:
  527.        dctmsg(MSG_INV_TYPE);
  528.        break;
  529.     }
  530.     if (index+1 > db_ArrayList[i].ar_count)
  531.         db_ArrayList[i].ar_count = index + 1;
  532.     return index;
  533. }
  534.  
  535.  
  536. /* 
  537. *    NAME:
  538. *       get_arv - get a value from an array
  539. *
  540. *    SYNOPSIS:
  541. *       int get_arv(id, s)
  542. *       char *id;   -- ASCIIZ name of array
  543. *       char *s;    -- offset expression
  544. *
  545. *    DESCRIPTION:
  546. *       Gets the value with the array id at offset s, and stores
  547. *       it into the appropriate dBASE variable.
  548. *   
  549. *    RETURNS:
  550. *       Returns index if successful, or -1 if an error occurs.
  551. *   
  552. */
  553.  
  554. get_arv(id, s)  
  555. char    *id;
  556. char    *s;
  557. {
  558. int i;
  559. int  index;
  560.  
  561. /* first see if the array exists */
  562.  
  563.     for (i = 0; i < MAXARRAYS; i++)
  564.     {
  565.      if (strccmp(db_ArrayList[i].ar_id, id) == 0)
  566.        break;
  567.     }
  568.     if (i == MAXARRAYS)
  569.     {
  570.      dctmsg(MSG_NO_ARRAY);
  571.      return -1;
  572.     }
  573.  
  574.     index = aroff(s, db_ArrayList[i].ar_dims);
  575.  
  576. /* see if the index is valid */
  577.     if (index >= db_ArrayList[i].ar_size)
  578.     {
  579.      dctmsg(MSG_OUT_OF_BOUNDS);
  580.      return(-1);
  581.     }
  582.  
  583.     switch (toupper(db_ArrayList[i].ar_type))
  584.     {
  585.     case 'C':
  586.        if (db_ArrayList[i].ar_val.vchar[index])
  587.            SetCRet(db_ArrayList[i].ar_val.vchar[index]);
  588.        break;
  589.     case 'N':
  590.        SetNRet(db_ArrayList[i].ar_val.vdub[index]);
  591.        break;
  592.     default:
  593.        dctmsg(MSG_INV_TYPE);
  594.        break;
  595.     }
  596.     return(index);
  597. }
  598.  
  599.  
  600. /* 
  601. *    NAME:
  602. *       dump_array - dump contents of an array
  603. *
  604. *    SYNOPSIS:
  605. *       dump_array(id, *f, *l)
  606. *       char *id;   -- name of array
  607. *       char *f;    -- offset from which to start
  608. *       char *l;    -- offset of last element to dump
  609. *
  610. *    DESCRIPTION:
  611. *       Beginning with the element whose offset is <f>, the values
  612. *       of <l> - <f> elements are displayed.
  613. *   
  614. *    RETURNS:
  615. *       Returns the number of elements in the array.
  616. */
  617.  
  618. dump_array(id,f,l)
  619. char    *id, *f, *l;
  620. {
  621. int i,j;
  622. int first, last;
  623.  
  624. /* first see if the array exists */
  625.  
  626.     for (i = 0; i < MAXARRAYS; i++)
  627.     {
  628.      if (strccmp(db_ArrayList[i].ar_id, id) == 0)
  629.         break;
  630.     }
  631.     if (i == MAXARRAYS)
  632.     {
  633.      dctmsg(MSG_NO_ARRAY);
  634.      return -1;
  635.     }
  636.  
  637.     first = aroff(f, db_ArrayList[i].ar_dims);
  638.     last = aroff(l,db_ArrayList[i].ar_dims);
  639.  
  640.     if (last > db_ArrayList[i].ar_size - 1)
  641.     {
  642.         dctmsg(MSG_OUT_OF_BOUNDS);
  643.         return(-1);
  644.     }
  645.  
  646.     if (db_ArrayList[i].ar_count == 0)
  647.         dctmsg(MSG_EMPTY);
  648.     else for (j = first; j <= (last ? last : db_ArrayList[i].ar_count-1); j++)
  649.     {
  650.         switch (toupper(db_ArrayList[i].ar_type))
  651.         {
  652.         case 'C':
  653.             printf("%5d %s\n", j, db_ArrayList[i].ar_val.vchar[j]);
  654.             break;
  655.         case 'N':
  656.             printf("%5d %f\n",j,db_ArrayList[i].ar_val.vdub[j]);
  657.             break;
  658.         default:
  659.             dctmsg(MSG_INV_TYPE);
  660.             break;
  661.         }
  662.         if (checkkey())
  663.             break;
  664.     }
  665.     return(db_ArrayList[i].ar_count);
  666. }
  667.  
  668.  
  669. /* 
  670. *    NAME:
  671. *       fdump_array - dump contents of an array to a file
  672. *
  673. *    SYNOPSIS:
  674. *       fdump_array(id, file, *f, *l)
  675. *       char *id;   -- name of array
  676. *       char *fname; -- name of file
  677. *       char *f;    -- offset from which to start
  678. *       char *l;    -- offset of last element to dump
  679. *
  680. *    DESCRIPTION:
  681. *       Beginning with the element whose offset is <f>, the values
  682. *       of <l> - <f> elements are written to the text file <fname>.
  683. *       If <fname> exists, it is overwritten with the new contents.
  684. *   
  685. *    RETURNS:
  686. *       Returns the number of elements in the array.
  687. */
  688.  
  689. fdump_array(id,fname,f,l)
  690. char    *id, *fname, *f, *l;
  691. {
  692. int i,j;
  693. int first, last;
  694. FILE    *fp;
  695.  
  696. /* first see if the array exists */
  697.  
  698.     for (i = 0; i < MAXARRAYS; i++)
  699.     {
  700.      if (strccmp(db_ArrayList[i].ar_id, id) == 0)
  701.         break;
  702.     }
  703.     if (i == MAXARRAYS)
  704.     {
  705.      dctmsg(MSG_NO_ARRAY);
  706.      return -1;
  707.     }
  708.     if ((fp = fopen(fname, "w")) == 0)
  709.     {
  710.         dctmsg(MSG_IO_ERROR);
  711.         return(-1);
  712.     }
  713.  
  714.     first = aroff(f, db_ArrayList[i].ar_dims);
  715.     last = aroff(l,db_ArrayList[i].ar_dims);
  716.  
  717.     if (last > db_ArrayList[i].ar_size - 1)
  718.     {
  719.         dctmsg(MSG_OUT_OF_BOUNDS);
  720.         return(-1);
  721.     }
  722.  
  723.     if (db_ArrayList[i].ar_count == 0)
  724.         dctmsg(MSG_EMPTY);
  725.     else for (j = first; j <= (last ? last : db_ArrayList[i].ar_count-1); j++)
  726.     {
  727.         switch (toupper(db_ArrayList[i].ar_type))
  728.         {
  729.         case 'C':
  730.             fprintf(fp, "%5d %s\n", j, db_ArrayList[i].ar_val.vchar[j]);
  731.             break;
  732.         case 'N':
  733.             fprintf(fp, "%5d %f\n",j,db_ArrayList[i].ar_val.vdub[j]);
  734.             break;
  735.         default:
  736.             dctmsg(MSG_INV_TYPE);
  737.             break;
  738.         }
  739.         if (checkkey()) /* pressing any key will abort display */
  740.             break;
  741.     }
  742.     fclose(fp);
  743.     return(db_ArrayList[i].ar_count);
  744. }
  745.  
  746.  
  747. /* 
  748. *    NAME:
  749. *       st_arrays - print status of arrays
  750. *
  751. *    SYNOPSIS:
  752. *       st_arrays();
  753. *
  754. *    DESCRIPTION:
  755. *       Prints a summary of the status of the arrays, including
  756. *       the name, type, and size of all arrays currently in use,
  757. *       as well as the number of arrays available to the user.
  758. *   
  759. *    RETURNS:
  760. *       Returns the number of available arrays.
  761. *       
  762. */
  763. extern char *BigBuf1;    /* this space was grapped on start-up */
  764. st_arrays()
  765. {
  766. int i,j;    
  767. int avail;
  768.  
  769.     for (i = 0,avail = MAXARRAYS; i < MAXARRAYS; i++)
  770.         if (*db_ArrayList[i].ar_id)
  771.             --avail;
  772.  
  773.     putwindow(1,0,(MAXARRAYS - avail)+3,79,BigBuf1);
  774.     for (i = 0,j = 0; i < MAXARRAYS; i++)
  775.     {
  776.         if (*db_ArrayList[i].ar_id) /* see if this one is used */
  777.         {
  778.             curlocat(2+j++,1); 
  779.             printf("    Array: %s, Type: %c, Size: %d, Count: %d\n",
  780.                 db_ArrayList[i].ar_id, db_ArrayList[i].ar_type,
  781.                 db_ArrayList[i].ar_size, db_ArrayList[i].ar_count);
  782.         }
  783.     }
  784.     curlocat(MAXARRAYS-avail+2,1);
  785. #ifdef LATTICE
  786.     printf("    There are %d arrays (and %ld bytes) available for use\n", 
  787.         avail,   sizmem() - ALLOC_OVHD <= 0L ? 
  788.             0L : sizmem()  - ALLOC_OVHD);
  789.  
  790. #else
  791.     printf("    There are %d arrays available for use\n", avail);
  792. #endif
  793.     getkeycl(&i);
  794.     if (i != 0x1b)
  795.         rstwindo(1,0,(MAXARRAYS - avail)+3,79,BigBuf1);
  796.  
  797.     return(avail);
  798. }
  799.  
  800.  
  801. /* 
  802. *    NAME:
  803. *       aroff - parse an offset expression
  804. *
  805. *    SYNOPSIS:
  806. *       int aroff(s,dims)
  807. *       char *s;    -- offset expression of form d1xd2x...xdn
  808. *           int dims[]; -- array of dimension sizes
  809. *
  810. *    DESCRIPTION:
  811. *       Calculates the actual offset of an expression, within an array
  812. *           beginning with offset 0 in each dimension.
  813. *   
  814. *    RETURNS:
  815. *       Returns the actual offset.
  816. *
  817. */
  818.  
  819. aroff(s,dims)
  820. char *s;    
  821. int *dims;
  822. {
  823. int size, n, i, temp;
  824.  
  825.  
  826.     n = 0;
  827.     size = 0;
  828.     while (*s)
  829.     {
  830.         temp = 1;
  831.         for (i = 0; i < n; i++)
  832.             temp *= dims[i];
  833.         size = atoi(s) * temp + size;
  834.         while (isdigit(*s))
  835.             s++;
  836.         if (toupper(*s) != 'X')
  837.             break;
  838.         s++;
  839.         n++;
  840.     }
  841.     return(size);
  842. }
  843.  
  844. /* 
  845. *    NAME:
  846. *       rest_arr    - restore an array from disk
  847. *
  848. *    SYNOPSIS:
  849. *       int rest_arr(id, name, start, end)
  850. *       char *id;   -- ASCIIZ name of array
  851. *       char *name; -- filename to use
  852. *       char *start;  -- dimension expression for first element
  853. *       char *end;    -- dimensional expression for last element
  854. *
  855. *    DESCRIPTION:
  856. *       Restores elements of the array id from the disk file name,
  857. *       beginning with <start> and ending with <end>.
  858. *       The file must have previously been created using save_arr().
  859. *   
  860. *    RETURNS:
  861. *       Returns the actual number of elements restored, which should
  862. *       normally be end-start+1, if successful, or -1 if not
  863. *   
  864. */
  865.  
  866. rest_arr(id, name, startexp, endexp)  
  867. char    *id;
  868. char    *name;
  869. char    *startexp,*endexp;
  870. {
  871. int i, j;
  872. FILE    *fp;
  873. int start, end;
  874. char    offset[6];  /* will hold actual offset for put_arv */
  875. char    value[256]; /* temp repository for element value */
  876.  
  877. /* first see if the array exists */
  878.  
  879.     for (i = 0; i < MAXARRAYS; i++)
  880.     {
  881.      if (strccmp(db_ArrayList[i].ar_id, id) == 0)
  882.        break;
  883.     }
  884.     if (i == MAXARRAYS)
  885.     {
  886.      dctmsg(MSG_NO_ARRAY);
  887.      return 0;
  888.     }
  889.  
  890.     start = aroff(startexp, db_ArrayList[i].ar_dims);
  891.     end = aroff(endexp, db_ArrayList[i].ar_dims);
  892.     
  893.     if (start > end || end >= db_ArrayList[i].ar_size)
  894.     {
  895.      dctmsg(MSG_OUT_OF_BOUNDS);
  896.      return(0);
  897.     }
  898.  
  899.     if ((fp = fopen(name, "r")) == 0)
  900.         return(-1);
  901.  
  902. /* now read in out all the elements */
  903.     for (j = start; j <= end; j++)
  904.     {
  905.         if (fgets(value, 255, fp) == NULL)
  906.             break;
  907.         value[strlen(value)-1] = '\0'; /* chop off the newline */
  908.         sprintf(offset, "%u", j);
  909.         if (put_arv(id, offset, value) < 0) 
  910.         break;
  911.     }
  912.     fclose(fp);
  913.  
  914.     if (j > db_ArrayList[i].ar_count)
  915.         db_ArrayList[i].ar_count = j;
  916.     return(j);
  917. }
  918.  
  919. /* 
  920. *    NAME:
  921. *       save_arr    - save an array to disk
  922. *
  923. *    SYNOPSIS:
  924. *       int save_arr(id, name, start, end)
  925. *       char *id;   -- ASCIIZ name of array
  926. *       char *name; -- filename to use
  927. *       char *start;  -- first element to save
  928. *       char *end;    -- last element to save
  929. *
  930. *    DESCRIPTION:
  931. *       Saves elements of the array id into a disk file, beginning
  932. *       with the <start> element and ending with <end>. If the
  933. *       file name already exists, it is written over.
  934. *   
  935. *    RETURNS:
  936. *       Returns the actual number of elements written, which should
  937. *       normally be <end>-<start>+1, if successful, or -1 if not
  938. *   
  939. */
  940.  
  941. save_arr(id, name, startexp, endexp)
  942. char    *id;
  943. char    *name;
  944. char    *startexp, *endexp;
  945. {
  946. int i,j;
  947. int start,end;
  948. FILE    *fp;
  949.  
  950. /* first see if the array exists */
  951.  
  952.     for (i = 0; i < MAXARRAYS; i++)
  953.     {
  954.      if (strccmp(db_ArrayList[i].ar_id, id) == 0)
  955.        break;
  956.     }
  957.     if (i == MAXARRAYS)
  958.     {
  959.      dctmsg(MSG_NO_ARRAY);
  960.      return 0;
  961.     }
  962.  
  963.     start = aroff(startexp, db_ArrayList[i].ar_dims);
  964.     end = aroff(endexp, db_ArrayList[i].ar_dims);
  965.     
  966.     if (start > end || end >= db_ArrayList[i].ar_size)
  967.     {
  968.      dctmsg(MSG_OUT_OF_BOUNDS);
  969.      return(0);
  970.     }
  971.     if ((fp = fopen(name, "w")) == 0)
  972.         return(-1);
  973.  
  974. /* now write out all the elements */
  975.     for (j = start; j <= end; j++)
  976.     {
  977.         switch (toupper(db_ArrayList[i].ar_type))
  978.         {
  979.         case 'C':
  980.             fprintf(fp, "%s\n", db_ArrayList[i].ar_val.vchar[j]);
  981.             break;
  982.         case 'N':
  983.             fprintf(fp, "%f\n", db_ArrayList[i].ar_val.vdub[j]);
  984.             break;
  985.         default:
  986.             dctmsg(MSG_INV_TYPE);
  987.             break;
  988.         }
  989.         if (ferror(fp))
  990.             return -1;
  991.     }
  992.  
  993.     return(fclose(fp) < 0 ? -1 : j);
  994. }
  995.  
  996. #ifdef LATTICE
  997. char *dctalloc(n, size)
  998. unsigned int    n;
  999. unsigned int size;
  1000. {
  1001.     return( (long)(n*size+ALLOC_OVHD) > sizmem() 
  1002.         ? (char *) 0 : calloc(n,size));
  1003. }
  1004. #endif
  1005.